package org.sea.mybator.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.sea.mybator.model.TableDesc;

public class Util {

    public static String firstCharToUpperCase(String columnName, String prefix) {
        if ((columnName == null) || ("".equals(columnName))) {
            return "";
        }
        String property = "";
        String[] names = columnName.split(prefix);
        if ((names != null) && (names.length > 0)) {
            property = names[0].trim().toLowerCase();
            if (names.length == 1) {
                return property;
            }
            for (int i = 1; i < names.length; i++) {
                String name = names[i].trim().toLowerCase();
                property = property + name.substring(0, 1).toUpperCase() + name.substring(1);
            }
        }

        return property;
    }

    public static String getVelocity(String templatePath, VelocityContext context) {
        VelocityEngine ve = new VelocityEngine();
        ve.init();
        Template t = ve.getTemplate(templatePath, "UTF-8");
        StringWriter writer = new StringWriter();
        t.merge(context, writer);
        return writer.toString();
    }

    public static String[] getPropertyName(String name) {
        String[] temps = name.split(" ");
        if ((temps != null) && (temps.length == 2))
            temps[1] = firstCharToUpperCase(temps[1], "_");
        else {
            temps[0] = firstCharToUpperCase(temps[0], "_");
        }
        return temps;
    }

    public static boolean writeFile(String name, String str, boolean isOverRide) {
        FileWriter fw = null;
        OutputStreamWriter ow = null;
        BufferedWriter bw = null;
        boolean flag = false;
        try {
            if (createFile(name, isOverRide)) {
                ow = new OutputStreamWriter(new FileOutputStream(name), "UTF-8");
                bw = new BufferedWriter(ow);

                bw.write(str, 0, str.length());
                bw.flush();
                flag = true;
                bw.close();
                ow.close();
            }
            System.err.println(name + "已经存在,请删除后再操作!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bw != null) {
                    bw.close();
                }
                if (fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return flag;
    }

    public static boolean writeFile(String name, String str) {
        FileWriter fw = null;
        BufferedWriter bw = null;
        boolean flag = false;
        try {
            File file = new File(name);
            fw = new FileWriter(file, true);
            bw = new BufferedWriter(fw);

            bw.write(str, 0, str.length());
            bw.flush();
            flag = true;
            bw.close();
            fw.close();
        } catch (IOException e) {
             e.printStackTrace();
        } finally {
            try {
                if (bw != null) {
                    bw.close();
                }
                if (fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return flag;
    }

    public static String[] regularMatcher(String regularPattern, String contents) {
        String[] keys = new String[0];
        if ((regularPattern == null) || (contents == null)) {
            return keys;
        }
        List<String> keysList = new ArrayList<String>();
        Pattern pattern = Pattern.compile(regularPattern);
        Matcher matcher = pattern.matcher(contents);
        while (matcher.find()) {
            String key = matcher.group();

            keysList.add(key);
        }
        if (keysList.size() > 0) {
            keys = new String[keysList.size()];
            for (int i = 0; i < keysList.size(); i++) {
                keys[i] = ((String) keysList.get(i));
            }
        }
        return keys;
    }

    public static String[] ignoredMatcher(String regularPattern, String contents, String ignoredString, String preSuffix) {
        StringReader sr = new StringReader(contents);
        BufferedReader br = new BufferedReader(sr);
        String s = "";
        String[] result = (String[]) null;
        try {
            List<String> keysList = new ArrayList<String>();
            while ((s = br.readLine()) != null) {
                int index = s.indexOf(ignoredString);
                String des = s;
                if (index != -1) {
                    des = s.substring(0, index);
                }
                String[] resultTemp = regularMatcher(regularPattern, des);
                int len = resultTemp.length;
                if ((resultTemp != null) && (len > 0)) {
                    if (index != -1) {
                        resultTemp[(len - 1)] = (resultTemp[(len - 1)] + preSuffix + s.substring(index));
                    }
                    for (String str : resultTemp) {
                        keysList.add(str);
                    }
                }
            }
            int size = keysList.size();
            if (size > 0) {
                result = new String[size];
                for (int i = 0; i < size; i++)
                    result[i] = ((String) keysList.get(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String getJavaType(TableDesc tableDesc, Map<String, String> javaTypeMap) {
        String typeName = tableDesc.getTypeName();

        if ((typeName == null) || ("".equals(typeName))) {
            System.err.println("getJavaType:typeName==null");
            return "";
        }
        String[] typeNames = typeName.split(" ");
        String key = typeNames[0];
        if (typeNames.length == 2) {
            key = key + "(" + typeNames[1] + ")";
        }

        key = key.toUpperCase();
        String value = (String) javaTypeMap.get(key);
        if ((value == null) || ("".equals(value))) {
            System.out.println("getJavaType:key=" + key + " not found mapping jdbcType!");
            return "";
        }
        String[] valueArr = value.split("@");
        if (valueArr.length == 1) {
            System.out.println("getJavaType:key=" + key + " value= " + value);
            return "";
        }
        return valueArr[1];
    }

    public static String getEntityType(TableDesc tableDesc, Map<String, String> javaTypeMap) {
        String typeName = tableDesc.getTypeName();

        if ((typeName == null) || ("".equals(typeName))) {
            System.err.println("getJavaType:typeName==null");
            return "";
        }
        String[] typeNames = typeName.split(" ");
        String key = typeNames[0];
        if (typeNames.length == 2) {
            key = key + "(" + typeNames[1] + ")";
        }

        key = key.toUpperCase();
        String value = (String) javaTypeMap.get(key);
        if ((value == null) || ("".equals(value))) {
            System.out.println("getJavaType:key=" + key + " not found mapping jdbcType!");
            return "";
        }
        String[] valueArr = value.split("@");
        if (valueArr.length == 1) {
            System.out.println("getJavaType:key=" + key + " value= " + value);
            return "";
        }
        return valueArr[0];
    }

    public static String firstLetterToUpperCase(String str) {
        if ((str == null) || ("".equals(str))) {
            return "";
        }
        if (str.length() == 1) {
            return str.toUpperCase();
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    public static String firstLetterToLowerCase(String str) {
        if ((str == null) || ("".equals(str))) {
            return "";
        }
        if (str.length() == 1) {
            return str.toLowerCase();
        }
        return str.substring(0, 1).toLowerCase() + str.substring(1);
    }

    public static String getDOName(String tableName) {
        if ((tableName == null) || ("".equals(tableName))) {
            return "defaultDOName";
        }
        String className = firstCharToUpperCase(tableName, "_");
        className = className.substring(0, 1).toUpperCase() + className.substring(1);
        return className;
    }

    public static String getAbstractDomainName(String tableName) {
        if ((tableName == null) || ("".equals(tableName))) {
            return "defaultAbstractDomainName";
        }
        String className = firstCharToUpperCase(tableName, "_");
        className = className.substring(0, 1).toUpperCase() + className.substring(1);
        return "Abstract" + className + "Domain";
    }

    public static String getModelName(String tableName) {
        if ((tableName == null) || ("".equals(tableName))) {
            return "defaultModelName";
        }
        String className = firstCharToUpperCase(tableName, "_");
        className = className.substring(0, 1).toUpperCase() + className.substring(1);
        return className;
    }

    public static String getQueryModelName(String tableName) {
        if ((tableName == null) || ("".equals(tableName))) {
            return "defaultModelName";
        }
        String className = firstCharToUpperCase(tableName, "_");
        className = className.substring(0, 1).toUpperCase() + className.substring(1);
        return className + "QueryBean";
    }

    public static String getDomainName(String tableName) {
        if ((tableName == null) || ("".equals(tableName))) {
            return "defaultDomainName";
        }
        String className = firstCharToUpperCase(tableName, "_");
        className = className.substring(0, 1).toUpperCase() + className.substring(1);
        return className + "Domain";
    }

    public static String getRepositoryName(String tableName) {
        if ((tableName == null) || ("".equals(tableName))) {
            return "defaultRepositoryName";
        }
        String className = firstCharToUpperCase(tableName, "_");
        className = className.substring(0, 1).toUpperCase() + className.substring(1);

        return className;
    }

    public static String getDaoName(String tableName) {
        if ((tableName == null) || ("".equals(tableName))) {
            return "defaultDaoName";
        }
        String className = firstCharToUpperCase(tableName, "_");
        className = className.substring(0, 1).toUpperCase() + className.substring(1);
        return className + "Dao";
    }

    public static String getContentsByFile(String filePath) {
        StringBuffer sb = new StringBuffer();
        FileReader fr = null;
        BufferedReader br = null;
        try {
            File file = new File(filePath);
            if ((file.exists()) && (file.isFile())) {
                fr = new FileReader(file);
                br = new BufferedReader(fr);
                String s = "";
                while ((s = br.readLine()) != null) {
                    sb.append(s).append("\r\n");
                }
                br.close();
                fr.close();
            }
            System.err.println(filePath + "不存在此文件！");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (fr != null)
                    br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        String result = sb.toString();
        if ((result == null) || ("".equals(result))) {
            return "";
        }
        return result.substring(0, result.length() - 2);
    }

    public static String getFilePath(String key, String fileName) {
       
        String filePath = null;
        if ((filePath == null) || ("".equals(filePath.trim()))) {
            filePath = Constants.createFilePath + key + File.separator;
            File file =new File(filePath);
            if(!file.exists()){
                file.mkdirs();
            }
        }
        return filePath + fileName;
    }

    public static String getFileName(String filePath) {
        File file = new File(filePath);
        return file.getName();
    }

    public static boolean writeFile(String templateName, VelocityContext context, String filePath) {
        try {
            String modelPath = Constants.TEMPLATEPATH + templateName;
            BufferedReader modelContents = getResource(modelPath);
            String xml = getVelocity(context, modelContents);
            if ((xml == null) || ("".equals(xml)))
                return false;
            return writeFile(filePath, xml, false);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static String getVelocity(VelocityContext context, BufferedReader modelContents) throws IOException {
        Velocity.init();
        StringWriter writer = new StringWriter();
        boolean flag = Velocity.evaluate(context, writer, "myFile", modelContents);
        if (flag) {
            String result = writer.getBuffer().toString();
            return result;
        }
        return "";
    }

    public static boolean removeFileContents(String regularPattern, String srcFilePath, String destFilePath) {
        try {
            File file = new File(srcFilePath);
            if ((file.exists()) && (file.isFile())) {
                FileReader fr = new FileReader(file);
                BufferedReader br = new BufferedReader(fr);
                StringBuffer sb = new StringBuffer();
                String s = "";
                while ((s = br.readLine()) != null) {
                    String[] temps = regularMatcher(regularPattern, s);
                    String temp = "";
                    if ((temps == null) || (temps.length == 0))
                        temp = s;
                    else {
                        temp = temps[0];
                    }

                    sb.append(temp).append("\r\n");
                }
                if ((destFilePath == null) || ("".equals(destFilePath))) {
                    destFilePath = "E:/auto/newFilela.txt";
                }
                writeFile(destFilePath, sb.toString(), false);
                br.close();
                fr.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static BufferedReader getResource(String filePath) throws IOException {
        InputStream is = Util.class.getResourceAsStream(filePath);
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        return br;
    }

    public static List<String> refreshFileList(String strPath, List<String> filelist, String[] fileTypes) {
        if (filelist == null) {
            filelist = new ArrayList<String>();
        }
        File dir = new File(strPath);
        if ((dir.isFile()) && (isInclude(dir.getName(), fileTypes))) {
            filelist.add(strPath);
            return filelist;
        }
        File[] files = dir.listFiles();
        if (files == null)
            return filelist;
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()) {
                refreshFileList(files[i].getAbsolutePath(), filelist, fileTypes);
            } else if (isInclude(files[i].getName(), fileTypes)) {
                filelist.add(files[i].getAbsolutePath());
            }
        }

        return filelist;
    }

    public static boolean isInclude(String fileName, String[] fileTypes) {
        if (fileName == null) {
            return false;
        }
        if ((fileTypes == null) || (fileTypes.length == 0)) {
            return true;
        }
        for (String s : fileTypes) {
            if (fileName.endsWith(s)) {
                return true;
            }
        }
        return false;
    }

    public static int countFileLines(String strPath, String[] fileTypes) {
        String[] fs = strPath.trim().split("\n");
        List<String> fileList = null;
        if ((fs != null) && (fs.length > 0)) {
            for (String f : fs) {
                fileList = refreshFileList(f.trim(), fileList, fileTypes);
            }
        }
        int count = 0;
        if ((fileList != null) && (fileList.size() > 0)) {
            try {
                for (String file : fileList) {
                    File f = new File(file);
                    boolean isCount = isInclude(f.getName(), fileTypes);
                    if (!isCount) {
                        continue;
                    }
                    int curr = 0;
                    BufferedReader bf = new BufferedReader(new FileReader(f));
                    while (bf.readLine() != null) {
                        curr++;
                        count++;
                    }
                    bf.close();
                    System.out.println(file + " : " + curr);
                    
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("总计：" + fileList.size() + "个文件," + count + "行");
     
        return count;
    }

    public static int vertifyFilesContents(String strPath, String queryKey, String[] fileTypes) {
        List<String> fileList = refreshFileList(strPath, null, fileTypes);
        int count = 0;
        if ((fileList != null) && (fileList.size() > 0)) {
            try {
                for (String file : fileList) {
                    File f = new File(file);
                    boolean isCount = isInclude(f.getName(), fileTypes);
                    if (!isCount) {
                        continue;
                    }
                    int curr = 0;
                    BufferedReader bf = new BufferedReader(new FileReader(f));
                    String s = "";
                    while ((s = bf.readLine()) != null) {
                        if ((s.indexOf(queryKey) <= -1) && (regularMatcher(queryKey, s).length <= 0))
                            continue;
                        curr++;
                        count++;
                    }

                    bf.close();
                    System.out.println(file + " : " + curr);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("总计：" + fileList.size() + "个文件," + count + "行");
        return count;
    }

    public static String[] listToString(List<String> list) {
        if ((list != null) && (list.size() > 0)) {
            String[] s = new String[list.size()];
            int i = 0;
            if (i < list.size()) {
                s[i] = String.valueOf(list.get(i));

                return s;
            }
        }
        return new String[0];
    }

    public static boolean createFile(String filePath, boolean isOverRide) {
        boolean flag = false;
        if ((filePath != null) && (!"".equals(filePath))) {
            int index = filePath.lastIndexOf(File.separator);
            String dir = "";
            if (index != -1) {
                dir = filePath.substring(0, index);
                File fileDir = new File(dir);
                if ((!fileDir.exists()) && (!fileDir.mkdirs())) {
                    System.err.println("创建目录：" + fileDir + "失败！");
                    return flag;
                }
            }

            File file = new File(filePath);
            if ((!file.exists()) || (isOverRide)) {
                try {
                    file.createNewFile();
                    flag = true;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

    public static boolean createPropertyFile(Map<String, String> map, String filePath) {
        boolean flag = false;
        try {
            if (createFile(filePath, true)) {
                Writer writers = new FileWriter(filePath);
                String propertys = mapToStringForProperty(map);
                if ((propertys == null) || ("".equals(propertys))) {
                    System.out.println("配置信息不能为空！");
                } else {
                    writers.write(propertys);
                    Properties prop = new Properties();
                    prop.store(writers, "autoCreate");
                    writers.close();
                    flag = true;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }

    public static boolean writeJarPropertyFile(Properties prop, String fileName) {
        boolean flag = false;
        try {
            String currentJarPath = URLDecoder.decode(Util.class.getProtectionDomain().getCodeSource().getLocation().getFile(),
                    "UTF-8");

            JarFile currentJar = new JarFile(currentJarPath);
            JarOutputStream out = new JarOutputStream(new FileOutputStream(currentJarPath));

            Iterator<Object> iterator = prop.keySet().iterator();
            while (iterator.hasNext()) {
                String key = (String) iterator.next();
                String value = (String) prop.get(key);
                JarEntry entry = new JarEntry(key);
                out.putNextEntry(entry);
                out.write(value.getBytes());
                out.flush();
            }
            flag = true;
            out.close();
            currentJar.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    public static boolean createPropertyFile(Properties prop, String filePath) {
        boolean flag = false;
        try {
            if (createFile(filePath, true)) {
                FileOutputStream writers = new FileOutputStream(filePath);

                prop.store(writers, "autoCreateFile config properties");

                writers.flush();
                writers.close();
                flag = true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }

    public static String mapToStringForProperty(Map<String, String> map) {
        StringBuffer propertys = new StringBuffer();
        if ((map != null) && (map.size() > 0)) {
            Iterator<String> iterator = map.keySet().iterator();
            while (iterator.hasNext()) {
                String key = (String) iterator.next();
                String value = (String) map.get(key);
                propertys.append(key).append("=").append(value).append("\r\n");
            }
        }
        return propertys.toString();
    }

    public static void write2JarFile(String filePath) {
        File original = new File(filePath);
        original.isFile();

        String originalPath = original.getAbsolutePath();

        String tempPath = originalPath.substring(0, originalPath.length() - 4) + "_temp.jar";
        System.out.println(tempPath);

        JarFile originalJar = null;
        try {
            originalJar = new JarFile(originalPath);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        List<JarEntry> lists = new LinkedList<JarEntry>();
        Enumeration<JarEntry> entrys = originalJar.entries();
        while (entrys.hasMoreElements()) {
            JarEntry jarEntry = (JarEntry) entrys.nextElement();

            lists.add(jarEntry);
        }

        File handled = new File(tempPath);
        JarOutputStream jos = null;
        try {
            FileOutputStream fos = new FileOutputStream(handled);
            jos = new JarOutputStream(fos);

            for (JarEntry je : lists) {
                JarEntry newEntry = new JarEntry(je.getName());

                jos.putNextEntry(newEntry);
                InputStream is = originalJar.getInputStream(je);
                byte[] bytes = inputStream2byteArray(is);
                is.close();

                jos.write(bytes);
            }

            jos.close();
            fos.close();

            deleteFiles(original);
            handled.renameTo(new File(originalPath));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static byte[] inputStream2byteArray(InputStream is) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] bytes = (byte[]) null;
        try {
            int i;
            while ((i = is.read()) != -1) {
                baos.write(i);
            }
            bytes = baos.toByteArray();
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bytes;
    }

    public static void deleteFiles(File directory) {
        if (directory.isFile()) {
            directory.delete();
            return;
        }

        File[] fileArr = directory.listFiles();
        for (File file : fileArr) {
            deleteFiles(file);
        }
        directory.delete();
    }

    public static String getProjectPath(boolean isIncludeFileName) {
        URL url = Util.class.getProtectionDomain().getCodeSource().getLocation();
        String filePath = null;
        try {
            filePath = URLDecoder.decode(url.getPath(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if ((filePath.endsWith(".jar")) && (!isIncludeFileName))
            filePath = filePath.substring(0, filePath.lastIndexOf("/") + 1);
        File file = new File(filePath);
        filePath = file.getAbsolutePath();
        return filePath;
    }

    public static String getRealPath() {
        String realPath = Util.class.getClassLoader().getResource("").getFile();
        File file = new File(realPath);
        realPath = file.getAbsolutePath();
        try {
            realPath = URLDecoder.decode(realPath, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return realPath;
    }

    public static void main(String[] args) {
      
    }
}
